﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using myFinance.Models;

namespace myFinance.BLL
{
	public class ContaBll
    {
        public static readonly Container db = new Container();

        /// <summary>
		/// Faz uma pesquisa e retorna a Conta pelo CodigoReferencia por usuário
		/// </summary>
		/// <param name="db">Container</param>
		/// <param name="id">Int</param>
		/// <returns>Conta</returns>
		public static Conta GetConta(int codigoreferencia, string usuario)
		{
			return db.Conta.FirstOrDefault(f => f.CodigoReferencia == codigoreferencia && f.Pessoa.Usuario == usuario);
		}

		/// <summary>
		/// Faz uma pesquisa e retorna o ultimo valor do CodigoReferencia por usuário
		/// </summary>
		/// <param name="db">Container</param>
		/// <param name="id">Int</param>
		/// <returns>Int</returns>
		public static int GetUltimoCodigoReferencia(string usuario)
		{
			if (db.Conta.FirstOrDefault(f => f.Pessoa.Usuario == usuario) != null)
			{
				return db.Conta.Where(w => w.Pessoa.Usuario == usuario).Max(m => m.CodigoReferencia) + 1;
			}
			else
			{
				return 1;
			}
		}

		#region Listas por Id de Pessoa
		/// <summary>
		/// Retorna uma lista de Contas (entradas e saídas) por id de usuário (Pessoa.Id) e por mês de cadastro/vencimento. Use cadastro == true para mês de cadastro ou cadastro == false para mês de vencimento.
		/// Use mes == 0 para trazer independente do mês
		/// </summary>
		/// <param name="db">Container</param>
		/// <param name="idPessoa">Int</param>
		/// <param name="mes">Int</param>
		/// <param name="cadastro">Bool</param>
		/// <returns>Lista de Contas</returns>
		public static List<Conta> GetLista(int idPessoa, int mes, int ano, bool cadastro)
		{
			if (mes == 0 && cadastro) return db.Conta.Where(w => w.PessoaId == idPessoa && w.DataCadastro.Year == ano).ToList();
			else if (mes == 0) return db.Conta.Where(w => w.PessoaId == idPessoa && w.DataVencimento.Year == ano).ToList();
			else if (cadastro) return db.Conta.Where(w => w.PessoaId == idPessoa && w.DataCadastro.Month == mes && w.DataCadastro.Year == ano).ToList();
			else return db.Conta.Where(w => w.PessoaId == idPessoa && w.DataVencimento.Month == mes && w.DataVencimento.Year == ano).ToList();
		}

		/// <summary>
		/// Retorna uma lista de Contas (entradas) por id de usuário (Pessoa.Id) e por mês de cadastro/vencimento. Use cadastro == true para mês de cadastro ou cadastro == false para mês de vencimento
		/// Use mes == 0 para trazer independente do mês
		/// </summary>
		/// <param name="db">Container</param>
		/// <param name="idPessoa">Int</param>
		/// <param name="mes">Int</param>
		/// <param name="cadastro">Bool</param>
		/// <returns>Lista de Contas</returns>
		public static List<Conta> GetListaEntradas(int idPessoa, int mes, int ano, bool cadastro)
		{
			if (mes == 0 && cadastro) return db.Conta.Where(w => w.PessoaId == idPessoa && w.Entrada == 1 && w.DataCadastro.Year == ano).ToList();
			else if (mes == 0) return db.Conta.Where(w => w.PessoaId == idPessoa && w.Entrada == 1 && w.DataVencimento.Year == ano).ToList();
			else if (cadastro) return db.Conta.Where(w => w.PessoaId == idPessoa && w.Entrada == 1 && w.DataCadastro.Month == mes && w.DataCadastro.Year == ano).ToList();
			else return db.Conta.Where(w => w.PessoaId == idPessoa && w.Entrada == 1 && w.DataVencimento.Month == mes && w.DataVencimento.Year == ano).ToList();
		}

		/// <summary>
		/// Retorna uma lista de Contas (saidas) por id de usuário (Pessoa.Id) e por mês de cadastro/vencimento. Use cadastro == true para mês de cadastro ou cadastro == false para mês de vencimento
		/// Use mes == 0 para trazer independente do mês
		/// </summary>
		/// <param name="db">Container</param>
		/// <param name="idPessoa">Int</param>
		/// <param name="mes">Int</param>
		/// <param name="cadastro">Bool</param>
		/// <returns>Lista de Contas</returns>
		public static List<Conta> GetListaSaidas(int idPessoa, int mes, int ano, bool cadastro)
		{
			if (mes == 0 && cadastro) return db.Conta.Where(w => w.PessoaId == idPessoa && w.Entrada == 2 && w.DataCadastro.Year == ano).ToList();
			else if (mes == 0) return db.Conta.Where(w => w.PessoaId == idPessoa && w.Entrada == 2 && w.DataVencimento.Year == ano).ToList();
			else if (cadastro) return db.Conta.Where(w => w.PessoaId == idPessoa && w.Entrada == 2 && w.DataCadastro.Month == mes && w.DataCadastro.Year == ano).ToList();
			else return db.Conta.Where(w => w.PessoaId == idPessoa && w.Entrada == 2 && w.DataVencimento.Month == mes && w.DataVencimento.Year == ano).ToList();

		}
		#endregion

		#region Listas por nome de Usuário
		/// <summary>
		/// Retorna uma lista de Contas (entradas e saídas) por nome de usuário (Pessoa.Usuario ou User.Identity.Name) e por mês de cadastro/vencimento. Use cadastro == true para mês de cadastro ou cadastro == false para mês de vencimento.
		/// Use mes == 0 para trazer independente do mês
		/// </summary>
		/// <param name="db">Container</param>
		/// <param name="usuario">String</param>
		/// <param name="mes">Int</param>
		/// <param name="cadastro">Bool</param>
		/// <returns>Lista de Contas</returns>
		public static List<Conta> GetLista(string usuario, int mes, int ano, bool cadastro)
		{
			if (mes == 0 && cadastro) return db.Conta.Where(w => w.Pessoa.Usuario == usuario && w.DataCadastro.Year == ano).ToList();
			else if (mes == 0) return db.Conta.Where(w => w.Pessoa.Usuario == usuario && w.DataVencimento.Year == ano).ToList();
			else if (cadastro) return db.Conta.Where(w => w.Pessoa.Usuario == usuario && w.DataCadastro.Month == mes && w.DataCadastro.Year == ano).ToList();
			else return db.Conta.Where(w => w.Pessoa.Usuario == usuario && w.DataVencimento.Month == mes && w.DataVencimento.Year == ano).ToList();
		}

		/// <summary>
		/// Retorna uma lista de Contas (entradas) por nome de usuário (Pessoa.Usuario ou User.Identity.Name) e por mês de cadastro/vencimento. Use cadastro == true para mês de cadastro ou cadastro == false para mês de vencimento.
		/// Use mes == 0 para trazer independente do mês
		/// </summary>
		/// <param name="db">Container</param>
		/// <param name="usuario">String</param>
		/// <param name="mes">Int</param>
		/// <param name="cadastro">Bool</param>
		/// <returns>Lista de Contas</returns>
		public static List<Conta> GetListaEntradas(string usuario, int mes, int ano, bool cadastro)
		{
			if (mes == 0 && cadastro) return db.Conta.Where(w => w.Pessoa.Usuario == usuario && w.Entrada == 1 && w.DataCadastro.Year == ano).ToList();
			else if (mes == 0) return db.Conta.Where(w => w.Pessoa.Usuario == usuario && w.Entrada == 1 && w.DataVencimento.Year == ano).ToList();
			else if (cadastro) return db.Conta.Where(w => w.Pessoa.Usuario == usuario && w.Entrada == 1 && w.DataCadastro.Month == mes && w.DataCadastro.Year == ano).ToList();
			else return db.Conta.Where(w => w.Pessoa.Usuario == usuario && w.Entrada == 1 && w.DataVencimento.Month == mes && w.DataVencimento.Year == ano).ToList();
		}

		/// <summary>
		/// Retorna uma lista de Contas (saídas) por nome de usuário (Pessoa.Usuario ou User.Identity.Name) e por mês de cadastro/vencimento. Use cadastro == true para mês de cadastro ou cadastro == false para mês de vencimento.
		/// Use mes == 0 para trazer independente do mês
		/// </summary>
		/// <param name="db">Container</param>
		/// <param name="usuario">String</param>
		/// <param name="mes">Int</param>
		/// <param name="cadastro">Bool</param>
		/// <returns>Lista de Contas</returns>
		public static List<Conta> GetListaSaidas(string usuario, int mes, int ano, bool cadastro)
		{
			if (mes == 0 && cadastro) return db.Conta.Where(w => w.Pessoa.Usuario == usuario && w.Entrada == 2 && w.DataCadastro.Year == ano).ToList();
			else if (mes == 0) return db.Conta.Where(w => w.Pessoa.Usuario == usuario && w.Entrada == 2 && w.DataVencimento.Year == ano).ToList();
			else if (cadastro) return db.Conta.Where(w => w.Pessoa.Usuario == usuario && w.Entrada == 2 && w.DataCadastro.Month == mes && w.DataCadastro.Year == ano).ToList();
			else return db.Conta.Where(w => w.Pessoa.Usuario == usuario && w.Entrada == 2 && w.DataVencimento.Month == mes && w.DataVencimento.Year == ano).ToList();
		}
		#endregion

		/// <summary>
		/// Grava a Conta no banco de dados
		/// </summary>
		/// <param name="db">Container</param>
		/// <param name="p">Conta</param>
		/// <returns>Boolean</returns>
		public static bool Add(Conta c)
		{
			db.Connection.Open();
			using (var transaction = db.Connection.BeginTransaction())
			{
				try
				{
					if (c.Parcelada)
					{
						var idPrincipal = 0;
						var valor = c.Valor / c.Parcelas;
						for (int i = 1; i <= c.Parcelas; i++)
						{
                            var novaConta = new Conta();                            
                            novaConta.Descricao = c.Descricao;
                            novaConta.Entrada = c.Entrada;
                            novaConta.GerarTarefa = c.GerarTarefa;
                            novaConta.GrupoDespesaId = c.GrupoDespesaId;
                            novaConta.Observacao = c.Observacao;                            
                            novaConta.Parcelada = c.Parcelada;
                            novaConta.Parcelas = c.Parcelas;
                            novaConta.PessoaId = c.PessoaId;
                            novaConta.Quitada = c.Quitada;
                            novaConta.SubGrupoDespesaId = c.SubGrupoDespesaId;
                            
							if (i == 1)
							{
                                novaConta.CodigoReferencia = c.CodigoReferencia;
                                novaConta.DataVencimento = c.DataVencimento;
                                novaConta.DataCadastro = DateTime.Now;
								novaConta.Parcela = i;
								novaConta.Valor = valor;

								db.Conta.AddObject(novaConta);
								idPrincipal = novaConta.Id;
                                								
                                if (novaConta.GerarTarefa)
                                {
                                    // inclui a tarefa						
                                    var tarefa = new Tarefa();
                                    tarefa.DataCadastro = DateTime.Now;
                                    tarefa.DataTarefa = novaConta.DataVencimento;
                                    tarefa.HoraInicio = new TimeSpan(8, 0, 0);
                                    tarefa.HoraFim = new TimeSpan(9, 0, 0);
									tarefa.Nome = "Pgto Conta Cód. Ref: " + novaConta.CodigoReferencia + ", no valor de: R$" + novaConta.Valor.ToString("N2") + ", Parcela: " + novaConta.Parcela + "/" + novaConta.Parcelas;
                                    tarefa.Descricao = "Pagar conta Cód. Ref: " + novaConta.CodigoReferencia + ", no valor de: R$" + novaConta.Valor.ToString("N2") + ", Parcela: " + novaConta.Parcela + "/" + novaConta.Parcelas;
                                    tarefa.PessoaId = novaConta.PessoaId;
                                    tarefa.Conta = novaConta;
                                    tarefa.Codigo = TarefaBll.GetUltimoCodigo(novaConta.PessoaId);
                                    db.Tarefa.AddObject(tarefa);                                    
                                }                                
							}
							else
							{
                                novaConta.DataCadastro = DateTime.Now;
                                novaConta.CodigoReferencia = c.CodigoReferencia + i - 1;
                                novaConta.DataVencimento = c.DataVencimento.AddMonths(i - 1);
								novaConta.Parcela = i;
								novaConta.Valor = valor;
								novaConta.IdContaPrincipal = idPrincipal;

								db.Conta.AddObject(novaConta);
								
                                if (novaConta.GerarTarefa)
                                {
                                    // inclui a tarefa						
                                    var tarefa = new Tarefa();
                                    tarefa.DataCadastro = DateTime.Now;
                                    tarefa.DataTarefa = novaConta.DataVencimento;
                                    tarefa.HoraInicio = new TimeSpan(8, 0, 0);
                                    tarefa.HoraFim = new TimeSpan(9, 0, 0);
									tarefa.Nome = "Pgto Conta Cód. Ref: " + novaConta.CodigoReferencia + ", no valor de: R$" + novaConta.Valor.ToString("N2") + ", Parcela: " + novaConta.Parcela + "/" + novaConta.Parcelas;
									tarefa.Descricao = "Pagar conta Cód. Ref: " + novaConta.CodigoReferencia + ", no valor de: R$" + novaConta.Valor.ToString("N2") + ", Parcela: " + novaConta.Parcela + "/" + novaConta.Parcelas;
                                    tarefa.PessoaId = novaConta.PessoaId;
                                    tarefa.Conta = novaConta;
                                    tarefa.Codigo = TarefaBll.GetUltimoCodigo(novaConta.PessoaId);
                                    db.Tarefa.AddObject(tarefa);
                                }	
							}
						}						
					}
					else
					{
						if (c.Parcelas > 1)
						{
							var idPrincipal = 0;
							for (int i = 1; i <= c.Parcelas; i++)
							{
                                var novaConta = new Conta();                                
                                novaConta.Descricao = c.Descricao;
                                novaConta.Entrada = c.Entrada;
                                novaConta.GerarTarefa = c.GerarTarefa;
                                novaConta.GrupoDespesaId = c.GrupoDespesaId;
                                novaConta.Observacao = c.Observacao;
                                novaConta.Parcelada = c.Parcelada;
                                novaConta.Parcelas = c.Parcelas;
                                novaConta.PessoaId = c.PessoaId;
                                novaConta.Quitada = c.Quitada;
                                novaConta.SubGrupoDespesaId = c.SubGrupoDespesaId;
                                novaConta.Valor = c.Valor;

                                if (i == 1)
                                {
                                    novaConta.CodigoReferencia = c.CodigoReferencia;
                                    novaConta.DataVencimento = c.DataVencimento;
                                    novaConta.DataCadastro = DateTime.Now;
                                    novaConta.Parcela = i;

                                    db.Conta.AddObject(novaConta);
                                    idPrincipal = novaConta.Id;

                                    if (novaConta.GerarTarefa)
                                    {
                                        // inclui a tarefa						
                                        var tarefa = new Tarefa();
                                        tarefa.DataCadastro = DateTime.Now;
                                        tarefa.DataTarefa = novaConta.DataVencimento;
                                        tarefa.HoraInicio = new TimeSpan(8, 0, 0);
                                        tarefa.HoraFim = new TimeSpan(9, 0, 0);
										tarefa.Nome = "Pgto Conta Cód. Ref: " + novaConta.CodigoReferencia + ", no valor de: R$" + novaConta.Valor.ToString("N2") + ", Parcela: " + novaConta.Parcela + "/" + novaConta.Parcelas;
										tarefa.Descricao = "Pagar conta Cód. Ref: " + novaConta.CodigoReferencia + ", no valor de: R$" + novaConta.Valor.ToString("N2") + ", Parcela: " + novaConta.Parcela + "/" + novaConta.Parcelas;
                                        tarefa.PessoaId = novaConta.PessoaId;
                                        tarefa.Conta = novaConta;
                                        tarefa.Codigo = TarefaBll.GetUltimoCodigo(novaConta.PessoaId);
                                        db.Tarefa.AddObject(tarefa);
                                    }
                                }
								else
								{
                                    novaConta.DataCadastro = DateTime.Now;
                                    novaConta.CodigoReferencia = c.CodigoReferencia + i - 1;
                                    novaConta.DataVencimento = c.DataVencimento.AddMonths(i - 1);
                                    novaConta.Parcela = i;
                                    novaConta.IdContaPrincipal = idPrincipal;

                                    db.Conta.AddObject(novaConta);                                    

                                    if (novaConta.GerarTarefa)
                                    {
                                        // inclui a tarefa						
                                        var tarefa = new Tarefa();
                                        tarefa.DataCadastro = DateTime.Now;
                                        tarefa.DataTarefa = novaConta.DataVencimento;
                                        tarefa.HoraInicio = new TimeSpan(8, 0, 0);
                                        tarefa.HoraFim = new TimeSpan(9, 0, 0);
										tarefa.Nome = "Pgto Conta Cód. Ref: " + novaConta.CodigoReferencia + ", no valor de: R$" + novaConta.Valor.ToString("N2") + ", Parcela: " + novaConta.Parcela + "/" + novaConta.Parcelas;
										tarefa.Descricao = "Pagar conta Cód. Ref: " + novaConta.CodigoReferencia + ", no valor de: R$" + novaConta.Valor.ToString("N2") + ", Parcela: " + novaConta.Parcela + "/" + novaConta.Parcelas;
                                        tarefa.PessoaId = novaConta.PessoaId;
                                        tarefa.Conta = novaConta;
                                        tarefa.Codigo = TarefaBll.GetUltimoCodigo(novaConta.PessoaId) + i -1;
                                        db.Tarefa.AddObject(tarefa);
                                    }	
								}
							}							
						}
						else
						{
                            c.DataCadastro = DateTime.Now;
							db.Conta.AddObject(c);

							if (c.GerarTarefa)
							{
								// inclui a tarefa						
								var tarefa = new Tarefa();
								tarefa.DataCadastro = DateTime.Now;
								tarefa.DataTarefa = c.DataVencimento;
								tarefa.HoraInicio = new TimeSpan(8, 0, 0);
								tarefa.HoraFim = new TimeSpan(9, 0, 0);
								tarefa.Nome = "Pgto Conta Cód. Ref: " + c.CodigoReferencia + ", no valor de: R$" + c.Valor.ToString("N2") + ", Parcela: " + c.Parcela + "/" + c.Parcelas;
								tarefa.Descricao = "Pagar conta Cód. Ref: " + c.CodigoReferencia + ", no valor de: R$" + c.Valor.ToString("N2") + ", Parcela: " + c.Parcela + "/" + c.Parcelas;
								tarefa.PessoaId = c.PessoaId;
								tarefa.Conta = c;
								tarefa.Codigo = TarefaBll.GetUltimoCodigo(c.PessoaId);
								db.Tarefa.AddObject(tarefa);
							}							
						}
					}

                    db.SaveChanges();
					transaction.Commit();
					return true;
				}
				catch (Exception ex)
				{
					throw ex;
				}
				finally
				{
					db.Connection.Close();
				}
			}
		}

		/// <summary>
		/// Altera a Conta no banco de dados
		/// </summary>
		/// <param name="db">Container</param>
		/// <param name="p">Conta</param>
		/// <returns>Boolean</returns>
		public static bool Edit(Conta c)
		{
			try
			{
				db.Conta.ApplyCurrentValues(c);
				db.SaveChanges();
				return true;
			}
			catch (Exception ex)
			{
				throw ex;
			}
		}

		/// <summary>
		/// Exclui uma Conta do banco de dados
		/// </summary>
		/// <param name="db">Container</param>
		/// <param name="p">Conta</param>
		/// <returns>Boolean</returns>
		public static bool Delete(int id)
		{
			try
			{
				var c = db.Conta.FirstOrDefault(f => f.Id == id);
				db.Conta.DeleteObject(c);
				db.SaveChanges();
				return true;
			}
			catch (Exception ex)
			{
				throw ex;
			}
		}

	}
}